#include "Model.h"
#include "Vertex.h"

#include "Graphics.h"
#include "Vec3.h"
#include "Vec2.h"

Model::Model()
{
	m_VertexBuffer = 0;
	m_IndexBuffer = 0;
}

Model::Model(const Model& other)
{
}

Model::~Model()
{
}

bool Model::Initialize()
{
	// Initialize the vertex and index buffer that hold the geometry for the triangle.
	if(!InitializeBuffers())
	{
		return false;
	}

	// Load the texture for this model.

	m_Texture = new Texture();
	m_Texture->Load("texture.jpg");

	return true;
}

void Model::Shutdown()
{
	// Release the vertex and index buffers.
	ShutdownBuffers();

	return;
}

void Model::Render()
{
	// Put the vertex and index buffers on the graphics pipeline to prepare them for drawing.
	RenderBuffers();

	return;
}

int Model::GetIndexCount()
{
	return m_IndexCount;
}

bool Model::InitializeBuffers()
{
	
	// Set the number of vertices in the vertex array.
	m_VertexCount = 4;

	// Set the number of indices in the index array.
	m_IndexCount = 6;

	//create two temporary arrays to hold the vertex and index data that we will use later to populate the final buffers with

	VertexPNT* vertices;
	// Create the vertex array.
	vertices = new VertexPNT[m_VertexCount];
	if(!vertices)
	{
		return false;
	}

	unsigned long* indices;
	// Create the index array.
	indices = new unsigned long[m_IndexCount];
	if(!indices)
	{
		return false;
	}

	// Load the vertex array with data.
	vertices[0].position = Vec3(-10.0f, -10.0f, 0.0f);  // Bottom left.
	vertices[0].normal = Vec3(0.0f, 0.0f, -1.0f);
	vertices[0].tex0 = Vec2(0.0f,1.0f);

	vertices[1].position = Vec3(-10.0f, 10.0f, 0.0f);  // Top middle.
	vertices[1].normal = Vec3(1.0f, 0.0f, -1.0f);
	vertices[1].tex0 = Vec2(0.0f,0.0f);

	vertices[2].position = Vec3(10.0f, 10.0f, 0.0f);  // Bottom right.
	vertices[2].normal = Vec3(1.0f, 0.0f, -1.0f);
	vertices[2].tex0 = Vec2(1.0f,0.0f);

	vertices[3].position = Vec3(10.0f, -10.0f, 0.0f);  // Bottom right.
	vertices[3].normal = Vec3(1.0f, 0.0f, -1.0f);
	vertices[3].tex0 = Vec2(1.0f,1.0f);

	// Load the index array with data.
	indices[0] = 0;  // Bottom left.
	indices[1] = 1;  // Top middle.
	indices[2] = 2;  // Bottom right.	

	indices[3] = 2;  // Bottom right.	
	indices[4] = 3;  // Bottom right.	
	indices[5] = 0;  // Bottom right.	
	

	D3D10_BUFFER_DESC vertexBufferDesc;
	// Set up the description of the vertex buffer.
	vertexBufferDesc.Usage = D3D10_USAGE_DEFAULT;
	vertexBufferDesc.ByteWidth = sizeof(VertexPNT) * m_VertexCount;
	vertexBufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
	vertexBufferDesc.CPUAccessFlags = 0;
	vertexBufferDesc.MiscFlags = 0;

	D3D10_SUBRESOURCE_DATA vertexData;
	// Give the subresource structure a pointer to the vertex data.
	vertexData.pSysMem = vertices;

	HRESULT result;
	// Now finally create the vertex buffer.
	result = TheGraphics::Instance()->GetD3DDevice()->CreateBuffer(&vertexBufferDesc, &vertexData, &m_VertexBuffer);
	if(FAILED(result))
	{
		return false;
	}

	D3D10_BUFFER_DESC indexBufferDesc;
	// Set up the description of the index buffer.
	indexBufferDesc.Usage = D3D10_USAGE_DEFAULT;
	indexBufferDesc.ByteWidth = sizeof(unsigned long) * m_IndexCount;
	indexBufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER;
	indexBufferDesc.CPUAccessFlags = 0;
	indexBufferDesc.MiscFlags = 0;

	D3D10_SUBRESOURCE_DATA indexData;
	// Give the subresource structure a pointer to the index data.
	indexData.pSysMem = indices;

	// Create the index buffer.
	result =  TheGraphics::Instance()->GetD3DDevice()->CreateBuffer(&indexBufferDesc, &indexData, &m_IndexBuffer);
	if(FAILED(result))
	{
		return false;
	}

	// Release the arrays now that the vertex and index buffers have been created and loaded.
	delete [] vertices;
	vertices = 0;

	delete [] indices;
	indices = 0;

	return true;
}

void Model::ShutdownBuffers()
{
	// Release the index buffer.
	if(m_IndexBuffer)
	{
		m_IndexBuffer->Release();
		m_IndexBuffer = 0;
	}

	// Release the vertex buffer.
	if(m_VertexBuffer)
	{
		m_VertexBuffer->Release();
		m_VertexBuffer = 0;
	}
	return;
}

void Model::RenderBuffers()
{
	unsigned int stride;
	unsigned int offset;

	// Set vertex buffer stride and offset.
	stride = sizeof(VertexPNT); 
	offset = 0;
    
	// Set the vertex buffer to active in the input assembler so it can be rendered
	TheGraphics::Instance()->GetD3DDevice()->IASetVertexBuffers(0, 1, &m_VertexBuffer, &stride, &offset);

	// Set the index buffer to active in the input assembler so it can be rendered
	TheGraphics::Instance()->GetD3DDevice()->IASetIndexBuffer(m_IndexBuffer, DXGI_FORMAT_R32_UINT, 0);

	// Set the type of primitive that should be rendered from this vertex buffer, in this case triangles.
	//TheGraphics::Instance()->GetD3DDevice()->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	TheGraphics::Instance()->GetD3DDevice()->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	return;
}